package com.lin.manager.secure.token;

import cn.hutool.core.date.DateUtil;
import com.lin.manager.secure.enums.SecurityEnum;
import com.lin.manager.secure.ex.CustomAccessDeniedException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @作者: 林江
 * @创建时间: 2024/3/15
 * @功能:
 */
public class JwtTokenGenerator implements TokenGenerator {

    /**
     * 签发人
     */
    private String iss = "javasystem";
    /**
     * 签发密匙
     */
    private String secret = "p1HE2dgQpqWsjWdDZp5sfe7Z1AXQAdcGTDCpluq9rFD4lQl6k3c8RSMpwnPfF69N";
    /**
     * 有效时长
     */
    private Long exp = Duration.ofHours(1L).getSeconds();
    /**
     * 加密方式
     */
    private static Map<String, Object> header = new HashMap<>();

    static {
        header.put("typ", "JWT");
        header.put("alg", "HS258");
    }

    public void setIss(String iss) {
        this.iss = iss;
    }

    public void setSecret(String secret) {
        this.secret = secret;
    }

    public void setExp(Long exp) {
        this.exp = exp;
    }

    public void setHeader(Map<String, Object> map) {
        if (Objects.nonNull(map)) {
            header.putAll(map);
        }
    }

    @Override
    public String generate(String payload) {
        return createToken(payload);
    }

    @Override
    public Object parse(String token) {
        return this.parseToken(token);
    }

    /**
     * 创建jwt
     *
     * @param payload
     * @return
     */
    public String createToken(String payload) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime localDateTime = now.plusSeconds(exp);
        String format = DateUtil.format(localDateTime, "yyyy-MM-dd HH:mm:ss");
        System.out.println("时间：" + format);

        String id = UUID.randomUUID().toString().replace("-", "").substring(1, 16);
        return Jwts.builder().setHeader(header).setId(id) // jwt唯一串
                // 设置负载内容
                .setClaims(new HashMap<String, Object>() {{
                    put("payload", payload);
                }}).setIssuer(iss).setIssuedAt(new Date())
                .setExpiration(DateUtil.parse(format))
                // 数字签名
                .signWith(SignatureAlgorithm.HS256, this.secret.getBytes(StandardCharsets.UTF_8)).compact();
    }

    /**
     * 解析token
     *
     * @param token
     * @return
     */
    public Claims parseToken(String token) {
        if (StringUtils.isEmpty(token)) {
            throw new CustomAccessDeniedException(SecurityEnum.LOGIN_FAIL_TOKEN_NULL);
        }

        try {
            return Jwts.parser().setSigningKey(this.secret.getBytes(StandardCharsets.UTF_8)).parseClaimsJws(token)
                    .getBody();
        } catch (ExpiredJwtException ex) {
            throw new CustomAccessDeniedException(SecurityEnum.LOGIN_FAIL_TOKEN_EXPIRED);
        } catch (Exception e) {
            throw new CustomAccessDeniedException(SecurityEnum.LOGIN_FAIL_TOKEN);
        }
    }
}
